﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using NetTopologySuite.Algorithm;

namespace NetTopologySuite.GeometriesGraph.Index
{
	public class SegmentIntersector
	{
		public static bool IsAdjacentSegments(int i1, int i2)
		{
			return System.Math.Abs(i1 - i2) == 1;
		}

		public SegmentIntersector(LineIntersector li, bool includeProper, bool recordIsolated)
		{
			this._li = li;
			this._includeProper = includeProper;
			this._recordIsolated = recordIsolated;
		}

		public void SetBoundaryNodes(IList<Node> bdyNodes0, IList<Node> bdyNodes1)
		{
			this._bdyNodes = new IList<Node>[2];
			this._bdyNodes[0] = bdyNodes0;
			this._bdyNodes[1] = bdyNodes1;
		}

		public Coordinate ProperIntersectionPoint
		{
			get
			{
				return this._properIntersectionPoint;
			}
		}

		public bool HasIntersection
		{
			get
			{
				return this._hasIntersection;
			}
		}

		public bool HasProperIntersection
		{
			get
			{
				return this._hasProper;
			}
		}

		public bool HasProperInteriorIntersection
		{
			get
			{
				return this._hasProperInterior;
			}
		}

		private bool IsTrivialIntersection(Edge e0, int segIndex0, Edge e1, int segIndex1)
		{
			if (e0 == e1 && this._li.IntersectionNum == 1)
			{
				if (SegmentIntersector.IsAdjacentSegments(segIndex0, segIndex1))
				{
					return true;
				}
				if (e0.IsClosed)
				{
					int num = e0.NumPoints - 1;
					if ((segIndex0 == 0 && segIndex1 == num) || (segIndex1 == 0 && segIndex0 == num))
					{
						return true;
					}
				}
			}
			return false;
		}

		public void AddIntersections(Edge e0, int segIndex0, Edge e1, int segIndex1)
		{
			if (e0 == e1 && segIndex0 == segIndex1)
			{
				return;
			}
			this.NumTests++;
			Coordinate p = e0.Coordinates[segIndex0];
			Coordinate p2 = e0.Coordinates[segIndex0 + 1];
			Coordinate p3 = e1.Coordinates[segIndex1];
			Coordinate p4 = e1.Coordinates[segIndex1 + 1];
			this._li.ComputeIntersection(p, p2, p3, p4);
			if (this._li.HasIntersection)
			{
				if (this._recordIsolated)
				{
					e0.Isolated = false;
					e1.Isolated = false;
				}
				this._numIntersections++;
				if (!this.IsTrivialIntersection(e0, segIndex0, e1, segIndex1))
				{
					this._hasIntersection = true;
					if (this._includeProper || !this._li.IsProper)
					{
						e0.AddIntersections(this._li, segIndex0, 0);
						e1.AddIntersections(this._li, segIndex1, 1);
					}
					if (this._li.IsProper)
					{
						this._properIntersectionPoint = (Coordinate)this._li.GetIntersection(0).Clone();
						this._hasProper = true;
						if (!SegmentIntersector.IsBoundaryPoint(this._li, this._bdyNodes))
						{
							this._hasProperInterior = true;
						}
					}
				}
			}
		}

		private static bool IsBoundaryPoint(LineIntersector li, IList<Node>[] bdyNodes)
		{
			return bdyNodes != null && (SegmentIntersector.IsBoundaryPoint(li, bdyNodes[0]) || SegmentIntersector.IsBoundaryPoint(li, bdyNodes[1]));
		}

		private static bool IsBoundaryPoint(LineIntersector li, IEnumerable<Node> bdyNodes)
		{
			foreach (Node node in bdyNodes)
			{
				Coordinate coordinate = node.Coordinate;
				if (li.IsIntersection(coordinate))
				{
					return true;
				}
			}
			return false;
		}

		private bool _hasIntersection;

		private bool _hasProper;

		private bool _hasProperInterior;

		private Coordinate _properIntersectionPoint;

		private readonly LineIntersector _li;

		private readonly bool _includeProper;

		private readonly bool _recordIsolated;

		private int _numIntersections;

		public int NumTests;

		private IList<Node>[] _bdyNodes;
	}
}
